﻿#include <QEventLoop>
#include <QThread>
#include <QDebug>

#include "common/AVAudioConvert.h"
#include "encode/AVFileStoreAAC.h"
#include "encode/AVFileStoreMP3.h"

extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include <libavutil/opt.h>
#include <libavutil/imgutils.h>
#include <libavutil/channel_layout.h>
#include <libavutil/samplefmt.h>
#include <libswresample/swresample.h>
#include <libavutil/time.h>
}

#include "AudioDataDispatcher.h"

AudioDataDispatcher::AudioDataDispatcher(QObject *parent):QObject(parent),
    m_micBuffer(16 * 1024,false),m_spkBuffer(16 * 1024,false)/* 16k的buffer足够了 */
{
    m_micBuffer.setWriteMode(LoopBuffer::WriteTotalUnlimited);
    m_micBuffer.open(QIODevice::ReadWrite);

    m_spkBuffer.setWriteMode(LoopBuffer::WriteTotalUnlimited);
    m_spkBuffer.open(QIODevice::ReadWrite);

    av_register_all();

    m_aac = new AVFileStoreAAC("test.aac");
    m_aac->init();

    m_mp3 = new AVFileStoreMP3("test.mp3");
    m_mp3->init();

}

AudioDataDispatcher::~AudioDataDispatcher()
{}

void AudioDataDispatcher::acceptMicData(AVFrame *frame)
{
    //    m_micList.push_back(frame);


    int writeBytes = av_samples_get_buffer_size(NULL,frame->channels,frame->nb_samples,(AVSampleFormat)frame->format,1);
    m_micBuffer.writeData((const char*)frame->data[0],writeBytes);
    av_frame_unref(frame);
    av_frame_free(&frame);
}

void AudioDataDispatcher::acceptSpeakerData(AVFrame *frame)
{
    //    m_speakList.push_back(frame);

    int writeBytes = av_samples_get_buffer_size(NULL,frame->channels,frame->nb_samples,(AVSampleFormat)frame->format,1);
    m_spkBuffer.writeData((const char*)frame->data[0],writeBytes);

    av_frame_unref(frame);
    av_frame_free(&frame);
}

void AudioDataDispatcher::acceptMacMicData(AVFrame *frame)
{
    int writeBytes = av_samples_get_buffer_size(NULL,frame->channels,frame->nb_samples,(AVSampleFormat)frame->format,1);
    m_micBuffer.writeData((const char*)frame->data[0],writeBytes);
    m_spkBuffer.writeData((const char*)frame->data[0],writeBytes);
}

void AudioDataDispatcher::run()
{
    QEventLoop loop;

    while (true) {
        loop.processEvents(QEventLoop::AllEvents);

        /* list暂时不用了，用了buffer */
        if (!m_micList.isEmpty()) {
            AVFrame *tempFrame = m_micList.first();
            av_frame_unref(tempFrame);
            av_frame_free(&tempFrame);
            m_micList.pop_front();
        }

        if (!m_speakList.isEmpty()) {
            AVFrame *tempFrame = m_speakList.first();
            av_frame_unref(tempFrame);
            av_frame_free(&tempFrame);
            m_speakList.pop_front();
        }

        const int nbsamples = 1024;
        int samples = 44100;
        int channels = 2;
        const int singleChannelSize = nbsamples * 1 * 2;

        char micBuf[singleChannelSize] = {0};
        char spkBuf[singleChannelSize] = {0};

        /* 关于数据回调不一致，读取的数据不一致的处理情况。 */
        if (m_spkBuffer.usedSize() >= singleChannelSize && m_micBuffer.usedSize() >= singleChannelSize) {

            AVFrame * dstFrame = av_frame_alloc();
            dstFrame->format = AV_SAMPLE_FMT_S16P;
            dstFrame->sample_rate = samples;
            dstFrame->nb_samples = nbsamples;
            dstFrame->channels = channels;
            dstFrame->channel_layout = av_get_default_channel_layout(dstFrame->channels);

            int dstSize = av_samples_get_buffer_size(NULL,dstFrame->channels,dstFrame->nb_samples,(AVSampleFormat)dstFrame->format,1);
            QByteArray bytes(dstSize,0);

            m_spkBuffer.readData(spkBuf,singleChannelSize);
            m_micBuffer.readData(micBuf,singleChannelSize);
            memcpy(bytes.data(),micBuf,singleChannelSize);
            memcpy(bytes.data() + singleChannelSize,spkBuf,singleChannelSize);

            int ret = avcodec_fill_audio_frame(dstFrame,dstFrame->channels,(AVSampleFormat)dstFrame->format,(uint8_t*)bytes.data(),dstSize,1);
            if (ret >= 0) {
                m_mp3->fillFrame(dstFrame);
                m_aac->fillFrame(dstFrame);
            } else {
                char buf[1024] = { 0 };
                av_strerror(ret, buf, sizeof(buf) - 1);
                qDebug() << "fill audio error" << ret << buf;
            }

//            static int i = 0;
//            i++;
//            if (i > 500) {
//                m_aac->destory();
//                exit(0);
//            }

            av_frame_unref(dstFrame);
            av_frame_free(&dstFrame);
        } else {
            QThread::msleep(20);
        }
    }
}
